From: Keir Fraser Date: Fri, 9 Jul 2010 15:45:42 +0000 (+0100) Subject: iommu: New options iommu=dom-strict and iommu=dom0-passthrough X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~11811 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https://%22%22/%22http:/www.example.com/cgi/%22https:/%22%22?a=commitdiff_plain;h=ecac002b16790a89ea5be574a940e0e174ea73a5;p=xen.git iommu: New options iommu=dom-strict and iommu=dom0-passthrough The former strips dom0 of its usual 1:1 mapping of all memory, and only provides it with mappings of its own memory, like any other domain. The latter is a new consistent name for iommu=passthrough. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index f1f28b7659..271cea5ef3 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -1462,12 +1462,18 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm) if ( ret ) goto destroy_m2p; - for ( i = spfn; i < epfn; i++ ) - if ( iommu_map_page(dom0, i, i, IOMMUF_readable|IOMMUF_writable) ) - break; - - if ( i != epfn ) - goto destroy_iommu; + if ( !need_iommu(dom0) ) + { + for ( i = spfn; i < epfn; i++ ) + if ( iommu_map_page(dom0, i, i, IOMMUF_readable|IOMMUF_writable) ) + break; + if ( i != epfn ) + { + while (i-- > old_max) + iommu_unmap_page(dom0, i); + goto destroy_m2p; + } + } /* We can't revert any more */ transfer_pages_to_heap(&info); @@ -1476,10 +1482,6 @@ int memory_add(unsigned long spfn, unsigned long epfn, unsigned int pxm) return 0; -destroy_iommu: - while (i-- > old_max) - iommu_unmap_page(dom0, i); - destroy_m2p: destroy_m2p_mapping(&info); max_page = old_max; diff --git a/xen/drivers/passthrough/amd/pci_amd_iommu.c b/xen/drivers/passthrough/amd/pci_amd_iommu.c index d1c97e3ae3..d0247d3305 100644 --- a/xen/drivers/passthrough/amd/pci_amd_iommu.c +++ b/xen/drivers/passthrough/amd/pci_amd_iommu.c @@ -231,7 +231,7 @@ static int amd_iommu_domain_init(struct domain *domain) { unsigned long i; - if ( !iommu_passthrough ) + if ( !iommu_passthrough && !need_iommu(domain) ) { /* setup 1:1 page table for dom0 */ for ( i = 0; i < max_page; i++ ) diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c index b592800a19..e755d6d59f 100644 --- a/xen/drivers/passthrough/iommu.c +++ b/xen/drivers/passthrough/iommu.c @@ -30,8 +30,8 @@ static int iommu_populate_page_table(struct domain *d); * force|required Don't boot unless IOMMU is enabled * workaround_bios_bug Workaround some bios issue to still enable VT-d, don't guarantee security - * passthrough Enable VT-d DMA passthrough (no DMA - * translation for Dom0) + * dom0-passthrough No DMA translation at all for Dom0 + * dom0-strict No 1:1 memory mapping for Dom0 * no-snoop Disable VT-d Snoop Control * no-qinval Disable VT-d Queued Invalidation * no-intremap Disable VT-d Interrupt Remapping @@ -39,6 +39,7 @@ static int iommu_populate_page_table(struct domain *d); custom_param("iommu", parse_iommu_param); bool_t __read_mostly iommu_enabled = 1; bool_t __read_mostly force_iommu; +bool_t __read_mostly iommu_dom0_strict; bool_t __read_mostly iommu_verbose; bool_t __read_mostly iommu_workaround_bios_bug; bool_t __read_mostly iommu_passthrough; @@ -64,8 +65,6 @@ static void __init parse_iommu_param(char *s) force_iommu = 1; else if ( !strcmp(s, "workaround_bios_bug") ) iommu_workaround_bios_bug = 1; - else if ( !strcmp(s, "passthrough") ) - iommu_passthrough = 1; else if ( !strcmp(s, "verbose") ) iommu_verbose = 1; else if ( !strcmp(s, "no-snoop") ) @@ -78,14 +77,18 @@ static void __init parse_iommu_param(char *s) amd_iommu_debug = 1; else if ( !strcmp(s, "amd-iommu-perdev-intremap") ) amd_iommu_perdev_intremap = 1; + else if ( !strcmp(s, "dom0-passthrough") ) + iommu_passthrough = 1; + else if ( !strcmp(s, "dom0-strict") ) + iommu_dom0_strict = 1; s = ss + 1; } while ( ss ); } -int iommu_domain_init(struct domain *domain) +int iommu_domain_init(struct domain *d) { - struct hvm_iommu *hd = domain_hvm_iommu(domain); + struct hvm_iommu *hd = domain_hvm_iommu(d); spin_lock_init(&hd->mapping_lock); INIT_LIST_HEAD(&hd->g2m_ioport_list); @@ -94,8 +97,10 @@ int iommu_domain_init(struct domain *domain) if ( !iommu_enabled ) return 0; + d->need_iommu = ((d->domain_id == 0) && iommu_dom0_strict); + hd->platform_ops = iommu_get_ops(); - return hd->platform_ops->init(domain); + return hd->platform_ops->init(d); } int iommu_add_device(struct pci_dev *pdev) @@ -276,6 +281,9 @@ int __init iommu_setup(void) { int rc = -ENODEV; + if ( iommu_dom0_strict ) + iommu_passthrough = 0; + if ( iommu_enabled ) { rc = iommu_hardware_setup(); @@ -290,8 +298,15 @@ int __init iommu_setup(void) iommu_snoop = 0; iommu_qinval = 0; iommu_intremap = 0; + iommu_passthrough = 0; + iommu_dom0_strict = 0; } printk("I/O virtualisation %sabled\n", iommu_enabled ? "en" : "dis"); + if ( iommu_enabled ) + printk(" - Dom0 mode: %s\n", + iommu_passthrough ? "Passthrough" : + iommu_dom0_strict ? "Strict" : "Relaxed"); + return rc; } diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index b8684141bb..1ed8f1f71b 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -1179,7 +1179,8 @@ static int intel_iommu_domain_init(struct domain *d) if ( d->domain_id == 0 ) { /* Set up 1:1 page table for dom0 */ - iommu_set_dom0_mapping(d); + if ( !need_iommu(d) ) + iommu_set_dom0_mapping(d); setup_dom0_devices(d); setup_dom0_rmrr(d);